import * as path from 'path'
import type { 
  RecoveryTask, 
  RecoveryResult, 
  BatchRecoveryResult,
  RecoveryOptions,
  BatchRecoveryOptions,
  RecoveryPreview,
  ConflictInfo,
  HistoryParser,
  FileOperations
} from '../types'
// Error types imported but not used - removing for now

// 活跃恢复操作的跟踪
interface ActiveRecovery {
  id: string
  tasks: RecoveryTask[]
  startTime: number
  cancelled: boolean
  progress: {
    completed: number
    total: number
    currentFile?: string
  }
}

export class RecoveryEngineImpl {
  private historyParser: HistoryParser
  private fileOperations: FileOperations
  private activeRecoveries = new Map<string, ActiveRecovery>()
  private recoveryIdCounter = 0

  constructor(historyParser: HistoryParser, fileOperations: FileOperations) {
    this.historyParser = historyParser
    this.fileOperations = fileOperations
  }

  /**
   * 恢复单个文件
   */
  async recoverFile(
    versionId: string, 
    fileId: string, 
    targetPath: string, 
    options: RecoveryOptions
  ): Promise<RecoveryResult> {
    try {
      // 验证输入参数
      const validationError = this.validateRecoveryParams(versionId, fileId, targetPath)
      if (validationError) {
        return {
          success: false,
          targetPath,
          error: validationError,
          bytesWritten: 0
        }
      }

      // 检查路径遍历攻击
      if (this.isPathTraversalAttack(targetPath)) {
        return {
          success: false,
          targetPath,
          error: 'Invalid target path: path traversal detected',
          bytesWritten: 0
        }
      }

      // 检查目标文件是否存在
      const targetExists = await this.fileOperations.fileExists(targetPath)
      if (targetExists && !options.overwrite) {
        return {
          success: false,
          targetPath,
          error: 'Target file already exists and overwrite is disabled',
          bytesWritten: 0
        }
      }

      // 从历史中获取文件内容
      const fileContent = await this.historyParser.getFileContent(versionId, fileId)
      
      // 创建目标目录（如果需要）
      if (options.createDirectories) {
        const targetDir = path.dirname(targetPath)
        await this.fileOperations.ensureDirectory(targetDir)
      }

      // 写入文件
      await this.fileOperations.writeFile(targetPath, fileContent)
      
      // 计算写入的字节数
      const bytesWritten = Buffer.byteLength(fileContent, 'utf8')

      // 保持时间戳（如果需要）
      if (options.preserveTimestamp) {
        try {
          const historyStats = await this.historyParser.getFileStats(versionId, fileId)
          if (historyStats.exists) {
            // 这里需要使用 fs.utimes 来设置时间戳，但为了简化，我们跳过这个功能
            // 在实际实现中，可以添加到 FileOperations 接口中
          }
        } catch (error) {
          // 时间戳设置失败不应该影响恢复操作
          console.warn('Failed to preserve timestamp:', error)
        }
      }

      return {
        success: true,
        targetPath,
        bytesWritten
      }

    } catch (error) {
      return {
        success: false,
        targetPath,
        error: error instanceof Error ? error.message : String(error),
        bytesWritten: 0
      }
    }
  }

  /**
   * 批量恢复文件
   */
  async batchRecover(
    tasks: RecoveryTask[], 
    options: BatchRecoveryOptions
  ): Promise<BatchRecoveryResult> {
    const startTime = Date.now()
    const successful: RecoveryResult[] = []
    const failed: RecoveryResult[] = []

    // 验证任务
    if (!tasks || tasks.length === 0) {
      return {
        successful,
        failed,
        totalCount: 0,
        duration: Date.now() - startTime
      }
    }

    // 创建活跃恢复跟踪
    const recoveryId = `recovery-${++this.recoveryIdCounter}`
    const activeRecovery: ActiveRecovery = {
      id: recoveryId,
      tasks,
      startTime,
      cancelled: false,
      progress: {
        completed: 0,
        total: tasks.length
      }
    }
    this.activeRecoveries.set(recoveryId, activeRecovery)

    try {
      // 将任务分组以控制并发
      const chunks = this.chunkArray(tasks, options.maxConcurrent)
      
      for (const chunk of chunks) {
        // 检查是否被取消
        if (activeRecovery.cancelled) {
          break
        }

        // 并发处理当前批次
        const promises = chunk.map(async (task) => {
          // 再次检查取消状态
          if (activeRecovery.cancelled) {
            return
          }

          // 更新当前处理的文件
          activeRecovery.progress.currentFile = task.originalPath

          try {
            const result = await this.recoverFile(
              task.versionId,
              task.fileId,
              task.targetPath,
              options
            )

            if (result.success) {
              successful.push(result)
            } else {
              failed.push(result)
              
              // 如果不继续处理错误，则停止
              if (!options.continueOnError) {
                activeRecovery.cancelled = true
                return
              }
            }
          } catch (error) {
            const failedResult: RecoveryResult = {
              success: false,
              targetPath: task.targetPath,
              error: error instanceof Error ? error.message : String(error),
              bytesWritten: 0
            }
            failed.push(failedResult)

            if (!options.continueOnError) {
              activeRecovery.cancelled = true
              return
            }
          }

          // 更新进度
          activeRecovery.progress.completed++
        })

        // 等待当前批次完成
        await Promise.allSettled(promises)
      }

    } finally {
      // 清理活跃恢复跟踪
      this.activeRecoveries.delete(recoveryId)
    }

    return {
      successful,
      failed,
      totalCount: tasks.length,
      duration: Date.now() - startTime
    }
  }

  /**
   * 预览恢复操作
   */
  async previewRecovery(tasks: RecoveryTask[]): Promise<RecoveryPreview> {
    const conflicts: ConflictInfo[] = []
    let totalSize = 0
    
    // 并发检查所有任务
    const conflictPromises = tasks.map(async (task) => {
      try {
        // 检查目标文件是否存在
        const targetExists = await this.fileOperations.fileExists(task.targetPath)
        
        let sizeConflict = false
        let historyFileSize = 0

        // 获取历史文件大小
        try {
          const fileContent = await this.historyParser.getFileContent(task.versionId, task.fileId)
          historyFileSize = Buffer.byteLength(fileContent, 'utf8')
          totalSize += historyFileSize
        } catch (error) {
          // 如果无法获取文件内容，记录为冲突
          conflicts.push({
            targetPath: task.targetPath,
            existingFile: false,
            sizeConflict: false
          })
          return
        }

        // 如果目标文件存在，检查大小冲突
        if (targetExists) {
          try {
            const targetStats = await this.fileOperations.getFileStats(task.targetPath)
            sizeConflict = targetStats.size !== historyFileSize
          } catch (error) {
            // 无法获取目标文件统计信息，假设有冲突
            sizeConflict = true
          }

          conflicts.push({
            targetPath: task.targetPath,
            existingFile: true,
            sizeConflict
          })
        }
      } catch (error) {
        // 处理检查过程中的错误
        conflicts.push({
          targetPath: task.targetPath,
          existingFile: false,
          sizeConflict: false
        })
      }
    })

    // 等待所有检查完成
    await Promise.allSettled(conflictPromises)

    // 估算恢复时间（基于文件大小和数量）
    const estimatedDuration = this.estimateRecoveryDuration(tasks.length, totalSize)

    return {
      tasks,
      conflicts,
      totalSize,
      estimatedDuration
    }
  }

  /**
   * 取消批量恢复操作
   */
  cancelBatchRecovery(recoveryId: string): boolean {
    const activeRecovery = this.activeRecoveries.get(recoveryId)
    if (activeRecovery) {
      activeRecovery.cancelled = true
      return true
    }
    return false
  }

  /**
   * 获取活跃的恢复操作
   */
  getActiveRecoveries(): ActiveRecovery[] {
    return Array.from(this.activeRecoveries.values())
  }

  /**
   * 获取恢复进度
   */
  getRecoveryProgress(recoveryId: string): ActiveRecovery | null {
    return this.activeRecoveries.get(recoveryId) || null
  }

  /**
   * 验证恢复参数
   */
  private validateRecoveryParams(versionId: string, fileId: string, targetPath: string): string | null {
    if (!versionId || versionId.trim() === '') {
      return 'Version ID is required'
    }
    
    if (!fileId || fileId.trim() === '') {
      return 'File ID is required'
    }
    
    if (!targetPath || targetPath.trim() === '') {
      return 'Target path is required'
    }
    
    return null
  }

  /**
   * 检查路径遍历攻击
   */
  private isPathTraversalAttack(targetPath: string): boolean {
    const normalizedPath = path.normalize(targetPath)
    return normalizedPath.includes('..') || normalizedPath.startsWith('/')
  }

  /**
   * 将数组分块以控制并发
   */
  private chunkArray<T>(array: T[], chunkSize: number): T[][] {
    const chunks: T[][] = []
    for (let i = 0; i < array.length; i += chunkSize) {
      chunks.push(array.slice(i, i + chunkSize))
    }
    return chunks
  }

  /**
   * 估算恢复时间
   */
  private estimateRecoveryDuration(fileCount: number, totalSize: number): number {
    // 基于经验的估算公式：
    // - 每个文件基础时间：50ms
    // - 每KB数据传输时间：1ms
    const baseTimePerFile = 50 // ms
    const timePerKB = 1 // ms
    
    const baseTime = fileCount * baseTimePerFile
    const dataTime = (totalSize / 1024) * timePerKB
    
    return Math.max(baseTime + dataTime, 100) // 最少100ms
  }


}

// Import dependencies for default instance
import { historyParser } from './history-parser'
import { fileOperations } from './file-operations'

// Create default instance
export const recoveryEngine = new RecoveryEngineImpl(historyParser, fileOperations)

// Factory function
export function createRecoveryEngine(
  historyParserInstance?: HistoryParser, 
  fileOperationsInstance?: FileOperations
): RecoveryEngineImpl {
  return new RecoveryEngineImpl(
    historyParserInstance || historyParser,
    fileOperationsInstance || fileOperations
  )
}